home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 9 / Night Owl CD-ROM (NOPV9) (Night Owl Publisher) (1993).ISO / 001a / seyon213.tz / seyon213 / seyon / SeDial.c < prev    next >
C/C++ Source or Header  |  1993-04-09  |  15KB  |  649 lines

  1.  
  2. /*
  3.  * This file is part of the Seyon, Copyright (c) 1992-1993 by Muhammad M.
  4.  * Saggaf. All rights reserved.
  5.  *
  6.  * See the file COPYING (1-COPYING) or the manual page seyon(1) for a full
  7.  * statement of rights and permissions for this program.
  8.  */
  9.  
  10. #include <signal.h>
  11. #include <setjmp.h>
  12. #include <sys/types.h>
  13. #include <sys/wait.h>
  14. #include <math.h>
  15.  
  16. #include <X11/Intrinsic.h>
  17. #include <X11/StringDefs.h>
  18. #include <X11/Shell.h>
  19. #include <X11/Xaw/Command.h>
  20. #include <X11/Xaw/Dialog.h>
  21. #include <X11/Xaw/Viewport.h>
  22. #include "MultiList.h"
  23.  
  24. #include "seyon.h"
  25. #include "SeDecl.h"
  26. #include "SeSig.h"
  27.  
  28. extern char    *get_word();
  29. extern int      IconifyShell(),
  30.                 MdmReadLine(),
  31.                 MdmTimedWaitFor();
  32. extern int      ConvertStringToIntArray();
  33.  
  34. int             ReadParsePhoneFile();
  35. void            DoDial(),
  36.                 ExecDial(),
  37.                 DismissDirectory(),
  38.                 DialerEnd(),
  39.                 HighlightItems(),
  40.                 ClearAllItems(),
  41.                 ManualDial(),
  42.                 DoManualDial(),
  43.                 ReReadPhoneFile();
  44.  
  45. struct _ddItem {
  46.   char            number[LIT_BUF];
  47.   char            name[LIT_BUF];
  48.   char            baud[10];
  49.   int             bits;
  50.   int             parity;
  51.   int             stopBits;
  52.   char            prefix[LIT_BUF];
  53.   char            suffix[LIT_BUF];
  54.   char            script[SM_BUF];
  55. };
  56.  
  57. struct _ddItem *ddItems[MAX_ENT];
  58. Boolean         dialDirUp = False,
  59.                 manualDial = False;
  60. char           *script_file,
  61.                 phone_number[SM_BUF] = "",
  62.                 dialMsg[SM_BUF];
  63. int             dialTime,
  64.                 dialTry,
  65.                 current_item,
  66.                 ddCurItemIndex;
  67. jmp_buf         dial_env;
  68. XfwfMultiListWidget mlw;
  69.  
  70. /*---------------------------------------------------------------------------+
  71. | TopDial - the top routine for the dialing directory.
  72. +---------------------------------------------------------------------------*/
  73.  
  74. void
  75. TopDial(widget, clientData)
  76.      Widget          widget;
  77.      XtPointer       clientData;
  78. {
  79.   void            EditFile();
  80.  
  81.   Widget          form, mBox, uBox, lBox, view, list;
  82.   static Widget   popup;
  83.   static char     phoneFile[REG_BUF];
  84.   static String   disItems[MAX_ENT+1] = {NULL};
  85.  
  86.   if (clientData == NULL && dialDirUp)
  87.     SimpleError("Directory is Already Open");
  88.  
  89.   if (disItems[0] == NULL) {
  90.     strcpy(phoneFile, qres.phoneFile);
  91.     if (ReadParsePhoneFile(phoneFile, disItems) < 0) return;
  92.  
  93.     form = XtParent(widget);
  94.     popup = SeAddPopupWG("directory", widget, form, form, 0,
  95.                          SeWidgetHeight(form), True, True);
  96.     mBox = AddPaned("mBox", popup);
  97.     uBox = AddBox("uBox", mBox);
  98.     lBox = AddBox("lBox", mBox);
  99.     
  100.     view = XtCreateManagedWidget("view", viewportWidgetClass, uBox, NULL, 0);
  101.     list = XtVaCreateManagedWidget("list", xfwfMultiListWidgetClass,
  102.                                    view, XtNlist, disItems, NULL);
  103.     mlw = (XfwfMultiListWidget)list;
  104.     SeSetViewportDimFromMultiList(view, list, 10);
  105.     XtAddCallback(list, XtNcallback, DoDial, NULL);
  106.     
  107.     AddButton("dismiss", lBox, DismissDirectory, NULL);
  108.     AddButton("ok", lBox, DoDial, NULL);
  109.     AddButton("manual", lBox, ManualDial, NULL);
  110.     AddButton("clear", lBox, ClearAllItems, NULL);
  111.     AddButton("default", lBox, HighlightItems, qres.defaultPhoneEntries);
  112.     AddButton("edit", lBox, EditFile, (XtPointer)phoneFile);
  113.     AddButton("reread", lBox, ReReadPhoneFile, (XtPointer)disItems);
  114.  
  115.     XtRealizeWidget(popup);
  116.   }
  117.  
  118.   if (clientData == NULL) {
  119.     XtPopup(popup, XtGrabNone);
  120.     dialDirUp = True;
  121.     if (qres.dialAutoStart) {
  122.       qres.dialAutoStart = False;
  123.       HighlightItems(widget, qres.defaultPhoneEntries);
  124.       DoDial();
  125.     }
  126.   }
  127.   else {
  128.       HighlightItems(widget, clientData);
  129.       DoDial();
  130.     }
  131. }
  132.  
  133. /*
  134.  * DoDial: gets the first selected item and dials it.
  135.  */
  136.  
  137. void
  138. DoDial()
  139. {
  140.   static XfwfMultiListReturnStruct *item;
  141.  
  142.   ErrorIfBusy();
  143.  
  144.   if ((item = XfwfMultiListGetHighlighted(mlw))->num_selected == 0)
  145.     SimpleError("No Item Selected");
  146.   ddCurItemIndex = item->selected_items[(current_item = 0)];
  147.  
  148.   inhibit_child = True;
  149.   manualDial = False;
  150.   dialTry = 1;
  151.   
  152.   PreProcessPrep();
  153.   ExecDial();
  154. }
  155.  
  156. /*
  157.  * executes the dialing as a forked process and communicates progress
  158.  * to the main process
  159.  */
  160.  
  161. void
  162. DialHandler(
  163. #if NeedFunctionPrototypes
  164.           int signo,
  165.           XtPointer client_data
  166. #endif
  167. )
  168. {
  169.   void            DispatchActions(),
  170.                   RunScript();
  171.  
  172. #if defined(SUNOS_3) || defined(Mips)
  173.   union wait      status;
  174. #else
  175.   int             status;
  176. #endif
  177.   Widget          dirWidget;
  178.  
  179.   if (wait(&status) < 0)
  180.     {SePError("Dial wait failed"); return;}
  181.   XoAppIgnoreSignal(app_con, SIGCHLD);
  182.  
  183. #if defined(SUNOS_3) || defined(Mips)
  184.   switch (status.w_retcode) {
  185. #else
  186.   switch (WEXITSTATUS(status)) {
  187. #endif
  188.   case 0:
  189.     SeyonMessage("Connected to Remote Host");
  190.     UpdateStatusBox(NULL);
  191.     DispatchActions(ACTION_DISPATCH, qres.postConnectAction, genericWidget);
  192.  
  193.     if ((dirWidget = XtNameToWidget(dialWidget, "directory"))) {
  194.       RemoveCurrentItem();
  195.       if (ddItems[ddCurItemIndex]->script[0] && !manualDial) {
  196.         linkflag = 1;
  197.         inhibit_child = False;
  198.         RunScript(ddItems[ddCurItemIndex]->script);
  199.         return;
  200.       }
  201.     }
  202.     break;
  203.   case 1:
  204.     DialCirculate();
  205.     return;
  206.   case 2:
  207.     Beep();
  208.     SeyonMessage("Dial Aborted: Online");
  209.     break;
  210.   case 10:
  211.     SeyonMessage("Dialing Canceled by User");
  212.     break;
  213.   }
  214.  
  215.   inhibit_child = False;
  216.   PostProcessPrep();
  217. }
  218.  
  219. /*
  220.  * KillDialHandler: signal handler for canceling the dialing process.
  221.  */
  222.  
  223. void
  224. KillDialHandler(
  225. #if NeedFunctionPrototypes
  226.           int signo
  227. #endif
  228. )
  229. {
  230.   void MdmOFlush();
  231.  
  232.   signal(SIGTERM, SIG_IGN);
  233.   MdmOFlush();
  234.   cancel_dial(0);
  235.   exit(10);
  236. }
  237.  
  238. void
  239. ExecDial()
  240. {
  241.   int        DialNumber();
  242.   static int retStatus;
  243.  
  244.   XoAppAddSignal(app_con, SIGCHLD, DialHandler, NULL);
  245.  
  246.   if ((w_child_pid = SeFork())) return;
  247.  
  248.   /* Child process */
  249.   signal(SIGTERM, KillDialHandler);
  250.   retStatus = DialNumber();
  251.   exit(retStatus);
  252. }
  253.  
  254. /*
  255.  * ReReadPhoneFile: updates the dialing directory from the phonebook file.
  256.  */
  257.  
  258. void
  259. ReReadPhoneFile(widget, disItems)
  260.      Widget          widget;
  261.      XtPointer       disItems[];
  262. {
  263.   Widget          dirWidget = XtParent(GetShell(widget));
  264.  
  265.   ErrorIfBusy();
  266.  
  267.   FreeList(disItems);
  268.   DestroyShell(widget);
  269.   dialDirUp = False;
  270.   TopDial(dirWidget, NULL);
  271. }
  272.  
  273. /*
  274.  * ManualDial: sets up the manual dialing popup.
  275.  */
  276.  
  277. void
  278. ManualDial(widget)
  279.      Widget          widget;
  280. {
  281.   Widget          popup;
  282.   
  283.   ErrorIfBusy();
  284.   popup = GetShell(PopupDialogGetValue("manual_dial", widget, DoManualDial, 
  285.                                        NULL, phone_number));
  286.   PopupCentered(popup, widget);
  287. }
  288.  
  289. /*
  290.  * action proc for manual dialing
  291.  */
  292.  
  293. void
  294. manual_dial_action_ok(widget)
  295.      Widget          widget;
  296. {
  297.   DoManualDial(widget);
  298. }
  299.  
  300. /*
  301.  * does manual dialing
  302.  */
  303.  
  304. void
  305. DoManualDial(widget)
  306.      Widget          widget;
  307. {
  308.   void            ExecManualDial();
  309.   Widget          dialog = XtParent(widget);
  310.   char            phoneNumber[SM_BUF];
  311.  
  312.   strcpy(phoneNumber, XawDialogGetValueString(dialog));
  313.   DestroyShell(dialog);
  314.   ExecManualDial(XtParent(GetShell(widget)), phoneNumber);
  315. }
  316.  
  317. void
  318. ExecManualDial(widget, phoneNumber)
  319.      Widget          widget;
  320.      String          phoneNumber;
  321. {
  322.   inhibit_child = True;
  323.   manualDial = True;
  324.  
  325.   strcpy(phone_number, phoneNumber);
  326.  
  327.   dialTry = 1;
  328.   PreProcessPrep();
  329.   ExecDial();
  330. }
  331.  
  332. /*
  333.  * DismissDirectory: dismisses the dialing directory.
  334.  */
  335.  
  336. void
  337. DismissDirectory(widget, clientData)
  338.      Widget          widget;
  339.      XtPointer       clientData;
  340. {
  341.   dialDirUp = False;
  342.   XtPopdown(GetShell(widget));
  343. }
  344.  
  345. /*
  346.  * ClearAllItems: clears all selected items.
  347.  */
  348.  
  349. void
  350. ClearAllItems()
  351. {
  352.   XfwfMultiListUnhighlightAll(mlw);
  353. }
  354.  
  355. void
  356. HighlightItems(widget, clientData)
  357.      Widget          widget;
  358.      XtPointer       clientData;
  359. {
  360.   int dialEntries[MAX_ENT], i;
  361.  
  362.   ConvertStringToIntArray((String*)clientData, dialEntries);
  363.  
  364.   ClearAllItems();
  365.   for (i = 0; dialEntries[i]; i++)
  366.     XfwfMultiListHighlightItem(mlw, dialEntries[i] - 1);
  367. }
  368.  
  369. /*
  370.  * unhighlights (unselects) the current item
  371.  */
  372.  
  373. void
  374. RemoveCurrentItem()
  375. {
  376.   static XfwfMultiListReturnStruct *item;
  377.  
  378.   item = XfwfMultiListGetHighlighted(mlw);
  379.   XfwfMultiListUnhighlightItem(mlw, item->selected_items[current_item]);
  380. }
  381.  
  382. /*
  383.  * circulates to the next selected item and dials it
  384.  */
  385.  
  386. void
  387. DialCirculate()
  388. {
  389.   static XfwfMultiListReturnStruct *item;
  390.  
  391.   if (manualDial)
  392.     dialTry++;
  393.   else {
  394.     item = XfwfMultiListGetHighlighted(mlw);
  395.     if (++current_item == item->num_selected) {
  396.       current_item = 0;
  397.       dialTry++;
  398.     }
  399.     ddCurItemIndex = item->selected_items[current_item];
  400.   }
  401.  
  402.   if (dialTry > qres.dialRepeat) {
  403.     SeyonMessage("Max Tries Exhausted");
  404.     inhibit_child = False;
  405.     PostProcessPrep();
  406.     return;
  407.   }
  408.  
  409.   ExecDial();
  410. }
  411.  
  412. void
  413. GetStrField(raw, keyword, var, def)
  414.      String          raw,
  415.                      keyword,
  416.                      var,
  417.                      def;
  418. {
  419.   char           *ptr,
  420.                   buf[REG_BUF],
  421.                   wrd[REG_BUF];
  422.  
  423.   if ((ptr = (char*)strstr(raw, keyword)) != NULL) {
  424.     ptr += strlen(keyword);
  425.     if (strncmp(ptr, "CURRENT", 3)) {
  426.       strcpy(buf, ptr);
  427.       GetWord(buf, wrd);
  428.       strcpy(var, wrd);
  429.     }
  430.     else
  431.       strcpy(var, "CURRENT");
  432.   }
  433.   else
  434.     strcpy(var, def);
  435. }
  436.  
  437. void
  438. GetIField(raw, keyword, var, def)
  439.      String          raw,
  440.                      keyword;
  441.      int            *var,
  442.                      def;
  443. {
  444.   char            svar[TIN_BUF],
  445.                   sdef[TIN_BUF];
  446.  
  447.   sprintf(svar, "%d", *var);
  448.   sprintf(sdef, "%d", def);
  449.  
  450.   GetStrField(raw, keyword, svar, sdef);
  451.  
  452.   if (strcmp(svar, "CURRENT"))
  453.     *var = atoi(svar);
  454.   else
  455.     *var = 100;
  456. }
  457.  
  458. #define DIALALARM 5
  459.  
  460. /*
  461.  * DialTimerHandler: alarm handler for dial timeout.
  462.  */
  463.  
  464. void
  465. DialTimerHandler(dummy)
  466.      int             dummy;
  467. {
  468.   void            DialTimerHandler();
  469.  
  470.   ProcRequest(SET_MESSAGE, FmtString("%s... %d", dialMsg, 
  471.                                      dialTime -= DIALALARM, ""), "");
  472.  
  473.   if (dialTime > 0) {
  474.     signal(SIGALRM, DialTimerHandler);
  475.     alarm(DIALALARM);
  476.   }
  477.   else {
  478.     signal(SIGALRM, SIG_DFL);
  479.     alarm(0);
  480.     strcpy(dialMsg, "TIMEOUT");
  481.     longjmp(dial_env, 1);
  482.   }
  483. }
  484.  
  485. /*
  486.  * DialNumber: this routine actually does the dialing.
  487.  */
  488.  
  489. int
  490. DialNumber()
  491. {
  492.   void            MdmIFlush();
  493.   char            modemResponse[SM_BUF],
  494.                  *itemName,
  495.                  *bufPtr,
  496.                   dialString[REG_BUF];
  497.   int             i,
  498.                   k;
  499.  
  500.   if (setjmp(dial_env) != 0) {
  501.     signal(SIGALRM, SIG_DFL);
  502.     alarm(0);
  503.  
  504.     ProcRequest(SET_MESSAGE, FmtString("%s: Sleeping (%ds)...", dialMsg, 
  505.                                        qres.dialDelay, ""), "");
  506.     cancel_dial(0);
  507.     sleep(qres.dialDelay);
  508.  
  509.     return 1;
  510.   }
  511.  
  512.   k = ddCurItemIndex;
  513.   dialTime = qres.dialTimeOut;
  514.  
  515.   if (!manualDial) {
  516.  
  517.     itemName = ddItems[k]->name;
  518.     sprintf(dialString, "\r%s %s%s", ddItems[k]->prefix, ddItems[k]->number,
  519.         ddItems[k]->suffix);
  520.  
  521.     if (mbaud(ddItems[k]->baud) < 0)
  522.       se_warningf("invalid BPS value in dialing directory: %s",
  523.           ddItems[k]->baud, "", "");
  524.     if (MdmSetGetCSize(ddItems[k]->bits) < 0)
  525.       se_warningf("invalid BITS value in dialing directory: %d",
  526.           ddItems[k]->bits, "", "");
  527.     if (MdmSetGetParity(ddItems[k]->parity) < 0)
  528.       se_warningf("invalid PARITY value in dialing directory: %d",
  529.           ddItems[k]->parity, "", "");
  530.     if (MdmSetGetStopBits(ddItems[k]->stopBits) < 0)
  531.       se_warningf("invalid STOPB value in dialing directory: %d",
  532.           ddItems[k]->stopBits, "", "");
  533.   }
  534.   else {
  535.     itemName = phone_number;
  536.     sprintf(dialString, "\r%s %s%s", qres.dialPrefix, phone_number,
  537.         qres.dialSuffix);
  538.   }
  539.  
  540.   if (dialTry == 1)
  541.     sprintf(dialMsg, "Dialing %s", itemName);
  542.   else
  543.     sprintf(dialMsg, "Redialing:%d %s", dialTry, itemName);
  544.  
  545.   ProcRequest(SET_MESSAGE, "Setting Up...", "");
  546.  
  547.   if (qres.hangupBeforeDial && (qres.ignoreModemDCD || Online())) MdmHangup();
  548.   if (!qres.ignoreModemDCD && Online())    return 2;
  549.  
  550.   ProcRequest(SET_MESSAGE, FmtString("%s... %d", dialMsg, dialTime, ""), "");
  551.  
  552.   MdmIFlush();
  553.   MdmPutString(dialString);
  554.   MdmPurge();
  555.  
  556.   signal(SIGALRM, DialTimerHandler);
  557.   alarm(DIALALARM);
  558.  
  559.   while (1) {
  560.     MdmReadLine(modemResponse);
  561.  
  562.     if (*(bufPtr = StripSpace(qres.connectString)) &&
  563.         strncmp(modemResponse, bufPtr, strlen(bufPtr)) == 0) {
  564.       alarm(0);
  565.       signal(SIGALRM, SIG_DFL);
  566.       showf("\r\n%s", modemResponse, "", "");
  567.       return 0;
  568.     }
  569.  
  570.     for (i = 0; i < 3; i++)
  571.       if (*(bufPtr = StripSpace(qres.noConnectString[i])) && 
  572.           strncmp(modemResponse, bufPtr, strlen(bufPtr)) == 0) {
  573.         strcpy(dialMsg, modemResponse);
  574.         longjmp(dial_env, 1);
  575.       }
  576.   }    /* while(1)... */
  577. }
  578.  
  579. int
  580. ReadParsePhoneFile(fname, disItems)
  581.      String          fname;
  582.      String          disItems[];
  583. {
  584.   FILE           *fp;
  585.   String          rawItems[MAX_ENT + 1];
  586.   char           *buf,
  587.                  *sHold,
  588.                   disItemsBuf[REG_BUF];
  589.   int             i,
  590.                   n,
  591.                   iHold;
  592.  
  593.   if ((fp = open_file(fname, qres.defaultDirectory)) == NULL)
  594.     return -1;
  595.  
  596.   ReadCommentedFile(fp, rawItems);
  597.   fclose(fp);
  598.  
  599.   FreeList(ddItems);
  600.   for (i = 0; (buf = rawItems[i]); i++) {
  601.  
  602.     /* Allocate the record */
  603.     ddItems[i] = XtNew(struct _ddItem);
  604.  
  605.     /* Find the number */
  606.     GetWord(buf, ddItems[i]->number);
  607. /*    strcpy(ddItems[i]->number, GetFirstWord(buf));*/
  608.  
  609.     /* Find the name */
  610.     GetWord((buf = lptr), ddItems[i]->name);
  611. /*    strcpy(ddItems[i]->name, GetNextWord());*/
  612.  
  613.     /* Find other stuff */
  614.     GetStrField(buf, "BPS=", ddItems[i]->baud, qres.defaultBPS);
  615.     GetIField(buf, "BITS=", &(ddItems[i]->bits), qres.defaultBits);
  616.     GetIField(buf, "PARITY=", &(ddItems[i]->parity), qres.defaultParity);
  617.     GetIField(buf, "STOPB=", &(ddItems[i]->stopBits), qres.defaultStopBits);
  618.     GetStrField(buf, "PREFIX=", ddItems[i]->prefix, qres.dialPrefix);
  619.     GetStrField(buf, "SUFFIX=", ddItems[i]->suffix, qres.dialSuffix);
  620.     GetStrField(buf, "SCRIPT=", ddItems[i]->script, "\000");
  621.   }
  622.   ddItems[i] = (struct _ddItem *)NULL;
  623.  
  624.   FreeList(rawItems);
  625.   FreeList(disItems);
  626.  
  627.   for (n = 0; n < i; n++) {
  628.     sprintf(disItemsBuf, qres.dialDirFormat,
  629.         ddItems[n]->name,
  630.         ddItems[n]->number,
  631.         strncmp((sHold = ddItems[n]->baud), "CUR", 3) ? sHold : "????",
  632.         (iHold = ddItems[n]->bits) == 100 ? '?' : itoa(iHold),
  633.         (iHold = ddItems[n]->parity) ? (iHold == 1 ? 'O' :
  634.                         (iHold == 2 ? 'E' : '?')) : 'N',
  635.         (iHold = ddItems[n]->stopBits) == 100 ? '?' : itoa(iHold),
  636.         strncmp((sHold = ddItems[n]->prefix), "CUR", 3) ?
  637.         strcmp(sHold, qres.dialPrefix) ? 'P' : 'D' : '?',
  638.         strncmp((sHold = ddItems[n]->suffix), "CUR", 3) ?
  639.         strcmp(sHold, qres.dialSuffix) ? 'S' : 'D' : '?',
  640.         ddItems[n]->script);
  641.  
  642.     disItemsBuf[SM_BUF - 1] = '\0';
  643.     disItems[n] = XtNewString(disItemsBuf);
  644.   }
  645.   disItems[n] = NULL;
  646.  
  647.   return 0;
  648. }
  649.